﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text.RegularExpressions;

namespace WebHelper.Helpers
{
    [Serializable]
    public class StringHelper
    {

        public StringHelper()
        {
        }

        //replace arabic letters in arabic satement
        public static string UnitArabicLetters(string statement,bool removeAbdWhiteSpace)
        {
            string s = statement;
            s = Regex.Replace(s, "[أآإ]", "ا");
            s = Regex.Replace(s, "ة", "ه");
            s = Regex.Replace(s, "ى", "ي");
            s = Regex.Replace(s, @"[ًٌٍَُِّْ~ـ]", "");//علامات الترقيم
            if (removeAbdWhiteSpace)
            {
                s = Regex.Replace(s, @"\bعبد\b\s*", " عبد");
                s = Regex.Replace(s, @"\bابو\b\s*", " ابو");
            }
            return s;
        }

        //to uni statement
        public static string ToUniqueStatement(string statement)
        {
            //statement = StringHelper.convertTapsAndNewLines(statement);
            if (statement != null)
            {
                statement = StringHelper.UnitArabicLetters(statement, true).ToLower();
                statement = StringHelper.RemoveSpaces(statement);
            }
            return statement;
        }

        //remove spaces 
        private static string RemoveSpaces(string statement)
        {
            statement = Regex.Replace(statement, " ", "");
            return statement;
        }

        //to one space
        public static string ToOneSpace(string statement)
        {
            statement = Regex.Replace(statement, @"\s+", " ");
            return statement;
        }
        
        // datatable containing  matching pairs in the statement
        public static DataTable getMatchingPairs(string Statement, bool curlyBrackets, bool roundBrackets, bool squareBrackets, bool anglBrackets, bool doubleQotation, bool singleQotation)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("openingPairPosition", typeof(int));
            dt.Columns.Add("closingPairPosition", typeof(int));
            dt.Columns.Add("type");

            Stack<int> curlyStack = new Stack<int>();   //{
            Stack<int> roundStack = new Stack<int>();   //(
            Stack<int> squareStack = new Stack<int>();   //[
            Stack<int> anglStack = new Stack<int>();   //<
            Stack<int> doubleQotationStack = new Stack<int>();   //"
            Stack<int> singleQotationStack = new Stack<int>();   //'

            MatchCollection matches= Regex.Matches(Statement, @"\{|\}|\(|\)|\[|\]|<|>|""|'");
            
            for (int i = 0; i < matches.Count; i++)
            {
                // curlyBrackets {}
                if (matches[i].Value == "{" && curlyBrackets)
                {
                    dt.Rows.Add(matches[i].Index, -1, "{");
                    curlyStack.Push(dt.Rows.Count - 1);
                }
                else if (matches[i].Value == "}" && curlyBrackets)
                {
                    if (curlyStack.Count > 0)
                    {
                        int rowNumber = curlyStack.Pop();
                        dt.Rows[rowNumber]["closingPairPosition"] = matches[i].Index;
                    }
                    else
                    {
                        dt.Rows.Add(-1, matches[i].Index, "{");
                    }
                }
                // roundBrackets()
                else if (matches[i].Value == "(" && roundBrackets)
                {
                    dt.Rows.Add(matches[i].Index, -1, "(");
                    roundStack.Push(dt.Rows.Count - 1);
                }
                else if (matches[i].Value == ")" && roundBrackets)
                {
                    if (roundStack.Count > 0)
                    {
                        int rowNumber = roundStack.Pop();
                        dt.Rows[rowNumber]["closingPairPosition"] = matches[i].Index;
                    }
                    else
                    {
                        dt.Rows.Add(-1, matches[i].Index, "(");
                    }
                }

                // squareBrackets []
                else if (matches[i].Value == "[" && squareBrackets)
                {
                    dt.Rows.Add(matches[i].Index, -1, "[");
                    squareStack.Push(dt.Rows.Count - 1);
                }
                else if (matches[i].Value == "]" && squareBrackets)
                {
                    if (squareStack.Count > 0)
                    {
                        int rowNumber = squareStack.Pop();
                        dt.Rows[rowNumber]["closingPairPosition"] = matches[i].Index;
                    }
                    else
                    {
                        dt.Rows.Add(-1, matches[i].Index, "[");
                    }
                }
                // anglBrackets <>
                else if (matches[i].Value == "<" && anglBrackets)
                {
                    dt.Rows.Add(matches[i].Index, -1, "<");
                    anglStack.Push(dt.Rows.Count - 1);
                }
                else if (matches[i].Value == ">" && anglBrackets)
                {
                    if (anglStack.Count > 0)
                    {
                        int rowNumber = anglStack.Pop();
                        dt.Rows[rowNumber]["closingPairPosition"] = matches[i].Index;
                    }
                    else
                    {
                        dt.Rows.Add(-1, matches[i].Index, ">");
                    }
                }
                //doubleQotation
                else if (matches[i].Value == @"""" && doubleQotation)
                {
                    if (doubleQotationStack.Count == 0)
                    {
                        dt.Rows.Add(matches[i].Index ,-1, "\"");
                        doubleQotationStack.Push(dt.Rows.Count - 1);
                    }
                    else
                    {
                        int rowNumber = doubleQotationStack.Pop();
                        dt.Rows[rowNumber]["closingPairPosition"] = matches[i].Index;
                    }
                }
                //singleQotation
                else if (matches[i].Value == "'" && singleQotation)
                {
                    if (singleQotationStack.Count == 0)
                    {
                        dt.Rows.Add(matches[i].Index, -1, "'");
                        singleQotationStack.Push(dt.Rows.Count - 1);
                    }
                    else
                    {
                        int rowNumber = singleQotationStack.Pop();
                        dt.Rows[rowNumber]["closingPairPosition"] = matches[i].Index;
                    }
                }
            }
            return dt;
        }

        public static int[] getMissingPairs(string statement,bool curlyBrackets, bool roundBrackets, bool squareBrackets, bool anglBrackets, bool doubleQotation, bool singleQotation)
        {
            List<int> list = new List<int>();
            DataTable dt = getMatchingPairs(statement, curlyBrackets, roundBrackets, squareBrackets, anglBrackets, doubleQotation, singleQotation);
            DataRow[] foundRows = dt.Select("openingPairPosition=-1 OR closingPairPosition=-1");
            for (int i = 0; i < foundRows.Length; i++)
            {
                int openPair = int.Parse(foundRows[i]["OpeningPairPosition"].ToString());
                int closePair = int.Parse(foundRows[i]["closingPairPosition"].ToString());
                int position = openPair;
                if (position == -1)
                {
                    position = closePair;
                }
                list.Add(position);
            }
            return list.ToArray();
        }

        public static int getpair(string statement, int charPosition)
        {
            DataTable dt = getMatchingPairs(statement, true, true, true, true, true, true);
            string filter=string.Format("openingPairPosition={0} OR closingPairPosition={0}",charPosition);
            DataRow[] foundRows = dt.Select(filter);
            int x = -1;
            if (foundRows.Length > 0)
            {
                int start = int.Parse(foundRows[0]["openingPairPosition"].ToString());
                int end= int.Parse(foundRows[0]["ClosingPairPosition"].ToString());
                if (charPosition == x)
                {
                    x = start;
                }
                else
                {
                    x = end;
                }
            }
            return x;
        }

        //replace with advanced suport for arabic and english
        public static string advancedReplace(string statement, string oldValue, string newvalue, bool exactAlef, bool exactYaa, bool exactHaa, bool excatDiacritics,bool matchCase, bool matchWholeWord)
        {
            string pattern = oldValue;
            if (!excatDiacritics)
            {
                pattern = Regex.Replace(pattern, "[ًٌٍَُِّْ~ـ]", "");
                pattern = Regex.Replace(pattern, @"(?<=\w)", "[ًٌٍَُِّْ~ـ]");
            }
            pattern = Regex.Escape(pattern);
            if (!exactAlef)
            {
                pattern=Regex.Replace(pattern,"[آاأإ]","[آاأإ]");
            }
            if (!exactYaa)
            {
                pattern = Regex.Replace(pattern, "[يى]", "[يى]");
            }
            if (!exactHaa)
            {
                pattern = Regex.Replace(pattern, "[ةه]", "[ةه]");
            }
            if (matchWholeWord)
            {
                pattern = @"\b" + pattern + @"\b";
            }
            string newStatement ="";
            if (matchCase)
            {
                newStatement = Regex.Replace(statement, pattern, newvalue.Trim());
            }
            else
            {
                newStatement = Regex.Replace(statement, pattern, newvalue.Trim(),RegexOptions.IgnoreCase);
            }
            return newStatement;
        }

        //convert string to html entities
        public static string getHtmlEntities(string text)
        {
            string htmlEntities = "";
            for (int i = 0; i < text.Length; i++)
            {
                if (text[i] == '&' && i < text.Length - 7)
                {
                    if (Regex.IsMatch(text.Substring(i, 8), @"&#x[0-9a-f]{1,4};"))
                    {
                        htmlEntities += text.Substring(i, 8);
                        i += 7;
                    }
                }
                else
                {
                    htmlEntities += String.Format("&#x{0}", Convert.ToUInt16(text[i]).ToString("x4")) + ";";
                }
            }
            return htmlEntities;
        }

        //convert html entities to text
        private static string getTextFromHtmlEntitiesEvaluator(Match m)
        {
            string s = m.Value.ToLower().Replace("&#x","").Replace(";","");
            int i=int.Parse(s, System.Globalization.NumberStyles.HexNumber);
            return ((char)i).ToString();
        }
        public static string getTextFromHtmlEntities(string htmlEntities)
        {
            string text = Regex.Replace(htmlEntities, @"&#x[0-9a-f]{1,4};", getTextFromHtmlEntitiesEvaluator, RegexOptions.IgnoreCase);
            return text;
        }

        //convert numbers to html arabic entities
        private static string ConvertNumbersToArabicEvaluator(Match m)
        {
            return ((char)(byte.Parse(m.Value) + 0x0660)).ToString();       
        }
        public static string ConvertNumbersToArabic(string text)
        {
            string s = Regex.Replace(text, @"\d", ConvertNumbersToArabicEvaluator, RegexOptions.IgnoreCase);
            return s;
        }

        public static DateTime getdate_yyyyMMdd(string s)
        {
            int year =Convert.ToInt32(s.Substring(0, 4));
            int month = Convert.ToInt32(s.Substring(4, 2));
            int day = Convert.ToInt32(s.Substring(6, 2));
            return new DateTime(year, month, day);
        }
        
        public static DateTime getdate_yyyyMMddHHmmss(string dateTimeString)
        {
            int year = Convert.ToInt32(dateTimeString.Substring(0, 4));
            int month = Convert.ToInt32(dateTimeString.Substring(4, 2));
            int day = Convert.ToInt32(dateTimeString.Substring(6, 2));

            int hour = Convert.ToInt32(dateTimeString.Substring(8, 2));
            int minute = Convert.ToInt32(dateTimeString.Substring(10, 2));
            int second = Convert.ToInt32(dateTimeString.Substring(12, 2));

            return new DateTime(year, month, day, hour, minute, second);
        }
        
        public static DateTime getdate_yyyyMMddHHmmss(string dateString, string timestring)
        {
            int year = Convert.ToInt32(dateString.Substring(0, 4));
            int month = Convert.ToInt32(dateString.Substring(4, 2));
            int day = Convert.ToInt32(dateString.Substring(6, 2));

            int hour = Convert.ToInt32(timestring.Substring(0, 2));
            int minute = Convert.ToInt32(timestring.Substring(2, 2));
            int second = Convert.ToInt32(timestring.Substring(4, 2));

            return new DateTime(year, month, day,hour,minute,second);
        }

    }
}
